package com.galaxy.device.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.galaxy.common.core.utils.MapstructUtils;
import com.galaxy.common.core.utils.StringUtils;
import com.galaxy.common.mybatis.core.page.PageQuery;
import com.galaxy.common.mybatis.core.page.TableDataInfo;
import com.galaxy.device.domain.*;
import com.galaxy.device.domain.bo.DeviceBaseBo;
import com.galaxy.device.domain.bo.DeviceStatusBo;
import com.galaxy.device.domain.convert.DeviceBaseConvert;
import com.galaxy.device.domain.vo.DeviceBaseVo;
import com.galaxy.device.domain.vo.DeviceChannelVo;
import com.galaxy.device.domain.vo.DeviceMaintenanceVo;
import com.galaxy.device.domain.vo.DeviceStockVo;
import com.galaxy.device.mapper.*;
import com.galaxy.device.service.IDeviceBaseService;
import com.galaxy.device.service.IDeviceEsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.geo.GeoPoint;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 设备基础信息Service业务层处理
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class DeviceBaseServiceImpl implements IDeviceBaseService {

    private final DeviceBaseMapper baseMapper;
    private final DeviceChannelMapper channelMapper;
    private final DeviceLocationMapper locationMapper;
    private final IDeviceEsService deviceEsService;
    private final DeviceStockMapper deviceStockService;
//    private final DeviceMachineTypeMapper machineTypeMapper;
    private static final String INDEX_NAME = "device";
    private final DeviceBaseMapper deviceBaseMapper;

    private final DeviceStatusMapper statusMapper;

    private final DeviceMaintenanceMapper deviceMaintenanceMapper;


    @DS("slave")
    @Override
    public DeviceBase queryById(Long id, Long type) {
        if (type != null && type == 0) {
            DeviceBase deviceBase = baseMapper.selectById(id);
            if (deviceBase == null) {
                return null;
            }
            return deviceBase;
        }else{
            // 使用联表查询一次性获取所有数据
            DeviceBase result = baseMapper.selectDeviceBaseWithDetails(id);
            return result;
        }
    }

    @DS("slave")
    @Override
    public DeviceBaseVo queryVoById(Long id, Long type) {
        if (type != null && type == 0) {
            DeviceBaseVo deviceBase = baseMapper.selectVoById(id);
            if (deviceBase == null) {
                return null;
            }
            return deviceBase;
        }else{
            // 使用联表查询一次性获取所有数据
            DeviceBaseVo result = baseMapper.selectDeviceBaseWithDetailsVo(id);
            return result;
        }
    }

    @DS("slave")
    @Override
    public String getDeviceNo(Long id) {
        DeviceBaseVo deviceBase = baseMapper.selectVoById(id);
        return deviceBase.getDeviceNo();
    }

    @Override
    public DeviceBaseVo getInfoByNo(String deviceNo) {
        DeviceBaseVo result = baseMapper.selectDeviceBaseWithDetailsVoByNo(deviceNo);
        return result;
    }

    @DS("slave")
    @Override
    public TableDataInfo<DeviceBaseVo> queryPageList(DeviceBaseBo bo, PageQuery pageQuery) {
//        LambdaQueryWrapper<DeviceBase> lqw = buildQueryWrapper(bo);
        IPage<DeviceBaseVo> page = baseMapper.selectVoListPage(pageQuery.build(), bo);
//        for (DeviceBaseVo deviceBaseVo : page.getRecords()){
//            deviceBaseVo.setDeviceType(machineTypeMapper.selectById(deviceBaseVo.getMachineTypeId()));
//        }
        return TableDataInfo.build(page);
    }

    @DS("slave")
    @Override
    public List<DeviceBaseVo> queryList(DeviceBaseBo bo) {
//        LambdaQueryWrapper<DeviceBase> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(bo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(DeviceBaseBo bo) {
        DeviceBase add = DeviceBaseConvert.INSTANCE.convert(bo);
        validEntityBeforeSave(add);
        add.setImgUrl(bo.getImgUrl());
        boolean flag = baseMapper.insert(add) > 0;
        DeviceStatusBo statusBo = new DeviceStatusBo();
        statusBo.setDeviceId(add.getId());
        statusBo.setMaintenanceCycle(30);
        DeviceStatus status = MapstructUtils.convert(statusBo, DeviceStatus.class);
        statusMapper.insert(status);

        if (flag) {
            bo.setId(add.getId());
            // 同步到ES
            syncToEs(add);
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(DeviceBaseBo bo) {
        DeviceBase update = DeviceBaseConvert.INSTANCE.convert(bo);
        update.setImgUrl(bo.getImgUrl());
        validEntityBeforeSave(update);
        boolean flag = baseMapper.updateById(update) > 0;
        if (flag) {
            // 同步到ES
            syncToEs(update);
        }
        return flag;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateStatusByDeviceNo(DeviceBaseBo bo) {
        DeviceBase update = deviceBaseMapper.selectOne(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getDeviceNo, bo.getDeviceNo()));
        if (update == null) {
            log.info("没有该设备！！！{}", bo.getDeviceNo());
            return false;
        }
        update.setStatus(bo.getStatus());
        boolean flag = baseMapper.updateById(update) > 0;
        if (flag) {
            // 同步到ES
            syncToEs(update);
        }
        return flag;
    }

    @Override
    public Boolean updateOfflineByDeviceNo(Long deviceID) {
        DeviceBase update = deviceBaseMapper.selectById(deviceID);
        if (update == null) {
            log.info("没有该设备！！！{}", deviceID);
            return false;
        }
        update.setStatus(5);
        boolean flag = baseMapper.updateById(update) > 0;
        if (flag) {
            // 同步到ES
            syncToEs(update);
        }
        return flag;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO: 做一些业务上的校验,判断是否允许删除
        }
        boolean flag = baseMapper.deleteBatchIds(ids) > 0;
        if (flag) {
            // 从ES中删除
            for (Long id : ids) {
                deviceMaintenanceMapper.delete(new LambdaQueryWrapper<DeviceMaintenance>().eq(DeviceMaintenance::getDeviceId, id));
                channelMapper.delete(new LambdaQueryWrapper<DeviceChannel>().eq(DeviceChannel::getDeviceId, id));
                deviceStockService.delete(new LambdaQueryWrapper<DeviceStock>().eq(DeviceStock::getDeviceId, id));
                locationMapper.delete(new LambdaQueryWrapper<DeviceLocation>().eq(DeviceLocation::getDeviceId, id));
                deviceEsService.deleteDevice(id.toString());
            }
        }
        return flag;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean updateCount(Long id, Integer count) {
        DeviceBase update = baseMapper.selectById(id);

        for (int i = 1; i <= count; i++) {
            DeviceChannelVo deviceChannelVo = channelMapper.selectVoOne(new LambdaQueryWrapper<DeviceChannel>()
                .eq(DeviceChannel::getDeviceId, id).eq(DeviceChannel::getChannelNo, i));
            if(deviceChannelVo == null){
                DeviceChannel channel = new DeviceChannel();
                channel.setDeviceId(update.getId());
                channel.setChannelNo(i + "");
                channel.setChannelPosition("A" + i);
                channel.setChannelType(1);
                channel.setMaxCapacity(10);
                channel.setStatus(1);
                channelMapper.insert(channel);
            }
        }

        for(int i = count + 1; i <= update.getChannelCount(); i++){
            DeviceChannelVo deviceChannelVo = channelMapper.selectVoOne(new LambdaQueryWrapper<DeviceChannel>()
                .eq(DeviceChannel::getDeviceId, id).eq(DeviceChannel::getChannelNo, i));
            channelMapper.delete(new LambdaQueryWrapper<DeviceChannel>()
                .eq(DeviceChannel::getDeviceId, update.getId()).eq(DeviceChannel::getChannelNo, i));
            deviceStockService.delete(new LambdaQueryWrapper<DeviceStock>()
                .eq(DeviceStock::getDeviceId, update.getId())
                .eq(DeviceStock::getChannelId, deviceChannelVo.getId())
            );
        }
        update.setChannelCount(count);
        boolean flag = baseMapper.updateById(update) > 0;
        if (flag) {
            // 同步到ES
            syncToEs(update);
        }
        return flag;
    }

    @Override
    public Long getTotalDevices() {
        return baseMapper.selectCount(null);
    }

    @Override
    public Long getOnlineDevices() {
        return baseMapper.selectCount(new LambdaQueryWrapper<DeviceBase>().eq(DeviceBase::getStatus, 1));
    }

    /**
     * 同步数据到ES
     */
    private void syncToEs(DeviceBase device) {
        try {
            // 1. 查询设备位置信息
            DeviceLocation location = locationMapper.selectOne(
                new LambdaQueryWrapper<DeviceLocation>()
                    .eq(DeviceLocation::getDeviceId, device.getId())
            );

            // 2. 构建设备ES对象
            DeviceEs deviceEs = new DeviceEs();
            deviceEs.setDeviceId(String.valueOf(device.getId()));
            deviceEs.setDeviceName(device.getDeviceName());
            deviceEs.setSiteId(String.valueOf(device.getManagerId()));
            deviceEs.setCreateTime(String.valueOf(device.getCreateTime()));
            deviceEs.setUpdateTime(String.valueOf(device.getUpdateTime()));

            // 3. 设置位置信息
            if (location != null && location.getLongitude() != null && location.getLatitude() != null) {
                GeoPoint geoPoint = new GeoPoint(
                    Double.parseDouble(String.valueOf(location.getLatitude())),
                    Double.parseDouble(String.valueOf(location.getLongitude()))
                );
                deviceEs.setLocation(geoPoint);
            }

            // 4. 保存或更新到ES
            deviceEsService.saveDevice(deviceEs);
        } catch (Exception e) {
            log.error("同步设备数据到ES失败: {}", e.getMessage());
        }
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(DeviceBase entity) {
        // TODO: 做一些实体的数据校验,如唯一约束
    }

    /**
     * 构建查询条件
     */
    private LambdaQueryWrapper<DeviceBase> buildQueryWrapper(DeviceBaseBo bo) {
        LambdaQueryWrapper<DeviceBase> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getDeviceNo()), DeviceBase::getDeviceNo, bo.getDeviceNo());
        lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), DeviceBase::getDeviceName, bo.getDeviceName());
        lqw.like(StringUtils.isNotBlank(bo.getSn()), DeviceBase::getSn, bo.getSn());
        lqw.like(StringUtils.isNotBlank(bo.getModel()), DeviceBase::getModel, bo.getModel());
        lqw.eq(bo.getMachineTypeId() != null, DeviceBase::getMachineTypeId, bo.getMachineTypeId());
        lqw.eq(bo.getManagerId() != null, DeviceBase::getManagerId, bo.getManagerId());
        lqw.eq(bo.getStatus() != null, DeviceBase::getStatus, bo.getStatus());
        return lqw;
    }
}
